package pers.whj.util.list;

import pers.whj.util.NoSuchElementException;

public class QueueList<T> extends LinkedList<T> implements Deque<T>, Stack<T> {
    private int mLengthLimit;
    private boolean mEnableLimit;

    public QueueList() {
        this(0);
    }

    public QueueList(int maxLength) {
        enableLimit(true, maxLength);
    }

    public void enableLimit(boolean enable, int maxLength) {
        if (enable && maxLength > 0) {
            mEnableLimit = true;
            mLengthLimit = maxLength;
        } else {
            mEnableLimit = false;
        }
    }

    public boolean isEnableLimit() {
        return mEnableLimit;
    }

    public int getLengthLimit() {
        return mLengthLimit;
    }

    @Override
    public boolean offerTail(T data) {
        checkForAdd();
        linkTail(data);
        return true;
    }

    @Override
    public boolean offerHead(T data) {
        checkForAdd();
        linkHead(data);
        return true;
    }

    @Override
    public T pollTail() {
        checkForRemove();
        return unlinkTail();
    }

    @Override
    public T pollHead() {
        checkForRemove();
        return unlinkHead();
    }

    @Override
    public T peekTail() {
        checkForRemove();
        return getTail();
    }

    @Override
    public T peekHead() {
        checkForRemove();
        return getHead();
    }

    @Override
    public int maxLength() {
        return mEnableLimit ? mLengthLimit : Integer.MAX_VALUE;
    }

    @Override
    public boolean push(T data) {
        checkForAdd();
        linkHead(data);
        return true;
    }

    @Override
    public T pop() {
        checkForRemove();
        return unlinkHead();
    }

    @Override
    public boolean offer(T data) {
        checkForAdd();
        linkTail(data);
        return true;
    }

    @Override
    public T poll() {
        checkForRemove();
        return unlinkHead();
    }

    @Override
    public T peek() {
        checkForRemove();
        return getHead();
    }

    @Override
    public boolean isFull() {
        return mEnableLimit && length() == mLengthLimit;
    }

    protected void checkForAdd() {
        if (mEnableLimit && length() == mLengthLimit) {
            throw new IllegalStateException("list is full, current length: " + length());
        }
    }

    protected void checkForRemove() {
        if (length() == 0) {
            throw new NoSuchElementException("list is empty");
        }
    }
}